<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Babylon.js GUI 2D图形示例</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <!-- 引入Babylon.js库 -->
    <script src="https://cdn.babylonjs.com/babylon.js"></script>
    <script src="https://cdn.babylonjs.com/gui/babylon.gui.min.js"></script>
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3B82F6',
            secondary: '#10B981',
            accent: '#8B5CF6',
            dark: '#1E293B',
            light: '#F8FAFC'
          },
          fontFamily: {
            sans: ['Inter', 'system-ui', 'sans-serif'],
          },
        },
      }
    }
  </script>
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .canvas-container {
        @apply relative w-full h-[500px] bg-gray-900 rounded-lg shadow-xl overflow-hidden;
      }
      .control-panel {
        @apply bg-gray-800 text-white p-4 rounded-lg shadow-lg transition-all duration-300;
      }
      .control-item {
        @apply mb-4 last:mb-0;
      }
      .btn {
        @apply px-4 py-2 rounded-md font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2;
      }
      .btn-primary {
        @apply bg-primary hover:bg-primary/90 text-white focus:ring-primary;
      }
      .btn-secondary {
        @apply bg-secondary hover:bg-secondary/90 text-white focus:ring-secondary;
      }
      .btn-accent {
        @apply bg-accent hover:bg-accent/90 text-white focus:ring-accent;
      }
      .btn-outline {
        @apply border border-gray-300 hover:bg-gray-700 text-white focus:ring-gray-500;
      }
      .input-field {
        @apply w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent;
      }
      .label {
        @apply block mb-2 text-sm font-medium text-gray-300;
      }
      .card {
        @apply bg-gray-800 rounded-xl shadow-lg overflow-hidden transition-all duration-300 hover:shadow-xl;
      }
      .card-header {
        @apply px-6 py-4 border-b border-gray-700;
      }
      .card-body {
        @apply px-6 py-4;
      }
    }
  </style>
</head>
<body class="bg-gray-900 text-light min-h-screen">
  <div class="container mx-auto px-4 py-8 max-w-6xl">
    <header class="mb-8 text-center">
      <h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold text-transparent bg-clip-text bg-gradient-to-r from-primary to-accent mb-2">
        Babylon.js GUI 2D图形演示
      </h1>
      <p class="text-gray-400 text-lg max-w-3xl mx-auto">
        使用 Babylon.js GUI 库创建交互式2D图形元素的示例，展示了如何绘制矩形、圆形、文本和按钮等基本UI组件。
      </p>
    </header>

    <main class="grid grid-cols-1 lg:grid-cols-3 gap-8">
      <!-- 左侧控制面板 -->
      <div class="lg:col-span-1 space-y-6">
        <div class="card">
          <div class="card-header">
            <h2 class="text-xl font-semibold">图形控制</h2>
          </div>
          <div class="card-body control-panel">
            <div class="control-item">
              <label class="label">选择图形类型</label>
              <select id="shapeType" class="input-field">
                <option value="rectangle">矩形</option>
                <option value="circle">圆形</option>
                <option value="ellipse">椭圆</option>
                <option value="text">文本</option>
                <option value="button">按钮</option>
              </select>
            </div>

            <div id="rectangleOptions" class="control-item">
              <label class="label">宽度</label>
              <input type="number" id="rectWidth" value="100" min="10" max="500" class="input-field">
            </div>

            <div id="rectangleHeight" class="control-item">
              <label class="label">高度</label>
              <input type="number" id="rectHeight" value="80" min="10" max="500" class="input-field">
            </div>

            <div id="circleOptions" class="control-item hidden">
              <label class="label">半径</label>
              <input type="number" id="circleRadius" value="50" min="10" max="250" class="input-field">
            </div>

            <div id="textOptions" class="control-item hidden">
              <label class="label">文本内容</label>
              <input type="text" id="textContent" value="Hello World!" class="input-field">
            </div>

            <div class="control-item">
              <label class="label">颜色</label>
              <input type="color" id="shapeColor" value="#3B82F6" class="w-full h-10 rounded-md">
            </div>

            <div class="control-item">
              <label class="label">描边颜色</label>
              <input type="color" id="outlineColor" value="#FFFFFF" class="w-full h-10 rounded-md">
            </div>

            <div class="control-item">
              <label class="label">描边宽度</label>
              <input type="number" id="outlineWidth" value="2" min="0" max="20" class="input-field">
            </div>

            <div class="control-item pt-2">
              <button id="createShape" class="btn btn-primary w-full flex items-center justify-center">
                <i class="fa fa-plus mr-2"></i> 创建图形
              </button>
            </div>
          </div>
        </div>

        <div class="card">
          <div class="card-header">
            <h2 class="text-xl font-semibold">交互控制</h2>
          </div>
          <div class="card-body control-panel">
            <div class="control-item">
              <button id="clearCanvas" class="btn btn-outline w-full flex items-center justify-center">
                <i class="fa fa-trash mr-2"></i> 清空画布
              </button>
            </div>
            <div class="control-item">
              <button id="addRandomShapes" class="btn btn-accent w-full flex items-center justify-center">
                <i class="fa fa-random mr-2"></i> 添加随机图形
              </button>
            </div>
            <div class="control-item">
              <div class="flex items-center">
                <input type="checkbox" id="enableDragging" checked class="w-5 h-5 rounded text-primary focus:ring-primary">
                <label for="enableDragging" class="ml-2 text-gray-300">启用拖拽</label>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 右侧画布区域 -->
      <div class="lg:col-span-2">
        <div class="card">
          <div class="card-header flex justify-between items-center">
            <h2 class="text-xl font-semibold">2D图形画布</h2>
            <div class="text-sm text-gray-400">
              <span id="shapeCount">图形数量: 0</span>
            </div>
          </div>
          <div class="card-body p-0">
            <div class="canvas-container">
              <canvas id="renderCanvas"></canvas>
              <div id="loadingIndicator" class="absolute inset-0 flex items-center justify-center bg-gray-900/80 z-10">
                <div class="flex flex-col items-center">
                  <div class="w-16 h-16 border-4 border-primary border-t-transparent rounded-full animate-spin"></div>
                  <p class="mt-4 text-gray-300">正在初始化场景...</p>
                </div>
              </div>
            </div>
          </div>
          <div class="p-4 border-t border-gray-700">
            <p class="text-gray-400 text-sm">
              <i class="fa fa-info-circle mr-1"></i> 提示: 点击"创建图形"按钮添加元素，或使用"添加随机图形"按钮快速生成多个图形。
              启用拖拽后可以移动画布上的图形元素。
            </p>
          </div>
        </div>
      </div>
    </main>

    <footer class="mt-12 text-center text-gray-500 text-sm">
      <p>© 2025 Babylon.js GUI 演示 | 使用 Tailwind CSS 和 Font Awesome 构建</p>
    </footer>
  </div>

  <script>
    // 全局变量
    let engine, scene, gui, advancedTexture, shapeCount = 0;
    const shapes = [];
    let isDraggingEnabled = true;
    
    // 初始化场景
    async function initScene() {
      const canvas = document.getElementById('renderCanvas');
      engine = new BABYLON.Engine(canvas, true);
      
      // 创建场景
      scene = new BABYLON.Scene(engine);
      scene.clearColor = new BABYLON.Color4(0.1, 0.1, 0.1, 1);
      
      // 创建相机
      const camera = new BABYLON.ArcRotateCamera("camera", 0, 0, 10, BABYLON.Vector3.Zero(), scene);
      camera.setPosition(new BABYLON.Vector3(0, 0, 10));
      camera.attachControl(canvas, true);
      
      // 创建灯光
      const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
      light.intensity = 0.7;
      
      // 创建GUI
      advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI("UI");
      
      // 隐藏加载指示器
      document.getElementById('loadingIndicator').style.display = 'none';
      
      // 注册事件监听器
      registerEventListeners();
      
      // 渲染循环
      engine.runRenderLoop(() => {
        scene.render();
      });
      
      // 处理窗口大小变化
      window.addEventListener('resize', () => {
        engine.resize();
      });
    }
    
    // 注册事件监听器
    function registerEventListeners() {
      // 图形类型选择
      const shapeTypeSelect = document.getElementById('shapeType');
      shapeTypeSelect.addEventListener('change', updateShapeOptions);
      
      // 创建图形按钮
      const createShapeBtn = document.getElementById('createShape');
      createShapeBtn.addEventListener('click', createSelectedShape);
      
      // 清空画布按钮
      const clearCanvasBtn = document.getElementById('clearCanvas');
      clearCanvasBtn.addEventListener('click', clearCanvas);
      
      // 添加随机图形按钮
      const addRandomShapesBtn = document.getElementById('addRandomShapes');
      addRandomShapesBtn.addEventListener('click', addRandomShapes);
      
      // 启用拖拽复选框
      const enableDraggingCheckbox = document.getElementById('enableDragging');
      enableDraggingCheckbox.addEventListener('change', (e) => {
        isDraggingEnabled = e.target.checked;
        updateDraggingState();
      });
    }
    
    // 更新形状选项显示
    function updateShapeOptions() {
      const shapeType = document.getElementById('shapeType').value;
      
      // 隐藏所有选项
      document.getElementById('rectangleOptions').classList.add('hidden');
      document.getElementById('rectangleHeight').classList.add('hidden');
      document.getElementById('circleOptions').classList.add('hidden');
      document.getElementById('textOptions').classList.add('hidden');
      
      // 显示选中形状的选项
      switch(shapeType) {
        case 'rectangle':
          document.getElementById('rectangleOptions').classList.remove('hidden');
          document.getElementById('rectangleHeight').classList.remove('hidden');
          break;
        case 'circle':
          document.getElementById('circleOptions').classList.remove('hidden');
          break;
        case 'text':
          document.getElementById('textOptions').classList.remove('hidden');
          break;
      }
    }
    
    // 创建选中的形状
    function createSelectedShape() {
      const shapeType = document.getElementById('shapeType').value;
      const color = document.getElementById('shapeColor').value;
      const outlineColor = document.getElementById('outlineColor').value;
      const outlineWidth = parseInt(document.getElementById('outlineWidth').value);
      
      // 随机位置
      const x = Math.random() * 0.8 - 0.4;
      const y = Math.random() * 0.8 - 0.4;
      
      let shape;
      
      switch(shapeType) {
        case 'rectangle':
          const width = parseInt(document.getElementById('rectWidth').value);
          const height = parseInt(document.getElementById('rectHeight').value);
          
          shape = new BABYLON.GUI.Rectangle(`rectangle${shapeCount}`);
          shape.width = `${width}px`;
          shape.height = `${height}px`;
          break;
          
        case 'circle':
          const radius = parseInt(document.getElementById('circleRadius').value);
          
          shape = new BABYLON.GUI.Ellipse(`circle${shapeCount}`);
          shape.width = `${radius * 2}px`;
          shape.height = `${radius * 2}px`;
          break;
          
        case 'ellipse':
          const ellipseWidth = parseInt(document.getElementById('rectWidth').value);
          const ellipseHeight = parseInt(document.getElementById('rectHeight').value);
          
          shape = new BABYLON.GUI.Ellipse(`ellipse${shapeCount}`);
          shape.width = `${ellipseWidth}px`;
          shape.height = `${ellipseHeight}px`;
          break;
          
        case 'text':
          const textContent = document.getElementById('textContent').value;
          
          shape = new BABYLON.GUI.TextBlock(`text${shapeCount}`, textContent);
          shape.fontSize = 24;
          shape.color = outlineColor; // 文本使用描边颜色作为文字颜色
          break;
          
        case 'button':
          shape = BABYLON.GUI.Button.CreateSimpleButton(`button${shapeCount}`, "按钮");
          shape.width = "120px";
          shape.height = "40px";
          shape.cornerRadius = 20;
          shape.color = "white";
          shape.background = color;
          shape.onPointerUpObservable.add(() => {
            alert("按钮被点击了!");
          });
          break;
      }
      
      // 基本属性设置
      if (shapeType !== 'text' && shapeType !== 'button') {
        shape.background = color;
        shape.thickness = outlineWidth;
        shape.color = outlineColor;
      }
      
      shape.horizontalAlignment = BABYLON.GUI.Control.HORIZONTAL_ALIGNMENT_CENTER;
      shape.verticalAlignment = BABYLON.GUI.Control.VERTICAL_ALIGNMENT_CENTER;
      shape.left = `${x * 100}%`;
      shape.top = `${y * 100}%`;
      
      // 添加到界面
      advancedTexture.addControl(shape);
      shapes.push(shape);
      
      // 更新计数
      shapeCount++;
      document.getElementById('shapeCount').textContent = `图形数量: ${shapeCount}`;
      
      // 设置拖拽
      if (shapeType !== 'button') {
        setupDragging(shape);
      }
    }
    
    // 设置元素拖拽
    function setupDragging(control) {
      if (!isDraggingEnabled) return;
      
      let isPointerDown = false;
      let lastPointerX, lastPointerY;
      
      control.onPointerDownObservable.add((eventData, eventState) => {
        isPointerDown = true;
        lastPointerX = eventData.globalX;
        lastPointerY = eventData.globalY;
        
        // 防止事件冒泡
        eventState.stopPropagation();
      });
      
      advancedTexture.onPointerMoveObservable.add((position) => {
        if (!isPointerDown) return;
        
        const deltaX = position.x - lastPointerX;
        const deltaY = position.y - lastPointerY;
        
        // 更新控件位置
        if (control.leftInPixels !== undefined) {
          control.leftInPixels += deltaX;
        } else {
          const currentLeft = parseFloat(control.left);
          const newLeft = currentLeft + (deltaX / advancedTexture.getSize().width * 100);
          control.left = `${newLeft}%`;
        }
        
        if (control.topInPixels !== undefined) {
          control.topInPixels += deltaY;
        } else {
          const currentTop = parseFloat(control.top);
          const newTop = currentTop + (deltaY / advancedTexture.getSize().height * 100);
          control.top = `${newTop}%`;
        }
        
        lastPointerX = position.x;
        lastPointerY = position.y;
      });
      
      advancedTexture.onPointerUpObservable.add(() => {
        isPointerDown = false;
      });
    }
    
    // 更新所有元素的拖拽状态
    function updateDraggingState() {
      // 清除所有现有拖拽事件
      shapes.forEach(shape => {
        shape.onPointerDownObservable.clear();
      });
      
      advancedTexture.onPointerMoveObservable.clear();
      advancedTexture.onPointerUpObservable.clear();
      
      // 重新设置拖拽
      if (isDraggingEnabled) {
        shapes.forEach(shape => {
          if (shape.name.startsWith('button')) return; // 按钮不支持拖拽
          setupDragging(shape);
        });
      }
    }
    
    // 清空画布
    function clearCanvas() {
      // 移除所有控件
      shapes.forEach(shape => {
        advancedTexture.removeControl(shape);
      });
      
      // 重置数组和计数
      shapes.length = 0;
      shapeCount = 0;
      document.getElementById('shapeCount').textContent = `图形数量: ${shapeCount}`;
    }
    
    // 添加随机图形
    function addRandomShapes() {
      const shapeTypes = ['rectangle', 'circle', 'ellipse', 'text'];
      const colors = ['#3B82F6', '#10B981', '#8B5CF6', '#F59E0B', '#EF4444'];
      const outlineColors = ['#FFFFFF', '#000000', '#E5E7EB', '#1F2937'];
      
      const count = Math.floor(Math.random() * 5) + 5; // 5-10个图形
      
      for (let i = 0; i < count; i++) {
        const shapeType = shapeTypes[Math.floor(Math.random() * shapeTypes.length)];
        const color = colors[Math.floor(Math.random() * colors.length)];
        const outlineColor = outlineColors[Math.floor(Math.random() * outlineColors.length)];
        const outlineWidth = Math.floor(Math.random() * 5) + 1;
        
        // 设置文档中的值
        document.getElementById('shapeType').value = shapeType;
        document.getElementById('shapeColor').value = color;
        document.getElementById('outlineColor').value = outlineColor;
        document.getElementById('outlineWidth').value = outlineWidth;
        
        if (shapeType === 'rectangle' || shapeType === 'ellipse') {
          document.getElementById('rectWidth').value = Math.floor(Math.random() * 150) + 50;
          document.getElementById('rectHeight').value = Math.floor(Math.random() * 150) + 50;
        } else if (shapeType === 'circle') {
          document.getElementById('circleRadius').value = Math.floor(Math.random() * 75) + 25;
        } else if (shapeType === 'text') {
          const texts = ['你好', 'Hello', 'Bonjour', 'Hola', 'Ciao', 'こんにちは'];
          document.getElementById('textContent').value = texts[Math.floor(Math.random() * texts.length)];
        }
        
        // 更新选项显示
        updateShapeOptions();
        
        // 创建图形
        createSelectedShape();
      }
    }
    
    // 初始化场景
    window.addEventListener('DOMContentLoaded', initScene);
  </script>
</body>
</html>
    